package com.ndp.fb.walle.util;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * Created by infi.he on 2016/3/30.
 */
public class MapUtils {
    private static Logger logger = LoggerFactory.getLogger(MapUtils.class);

    /**
     * 将list中的元素合并
     *
     * @param gaMapList
     * @param filterKeys
     * @return
     */
    public static List<Map<String, Object>> mergeMapList(List<Map<String, Object>> gaMapList, Set<String> filterKeys) {
        List<Map<String, Object>> tempList = new ArrayList<>();
        for (Map<String, Object> map : gaMapList) {
            addMap(tempList, map, filterKeys);
        }
        return tempList;
    }

    /**
     * 合并map的值
     *
     * @param mapList
     * @param keys
     * @return
     */
    public static List<Map<String, Object>> mergeMap(List<List<Map<String, Object>>> mapList, Collection<String> keys) {
        List<Map<String, Object>> result = null;
        for (int i = 0; i < mapList.size(); i++) {
            List<Map<String, Object>> maps = mapList.get(i);
            if (i == 0) {
                result = maps;
            } else {
                for (Map<String, Object> map : maps) {
                    addMap(result, map, keys);
                }
            }
        }
        return result;
    }

    public static void addMap(List<Map<String, Object>> mapList, Map<String, Object> map, Collection<String> keys) {
        //关键字 键值对
        Map<String, Object> filterKeyMap = extractFilterMap(map, keys);
        Map<String, Object> existsMap = existsMap(mapList, filterKeyMap);
        if (existsMap == null) {
            mapList.add(map);
        } else {
            for (Map.Entry<String, Object> stringObjectEntry : map.entrySet()) {
                String key = stringObjectEntry.getKey();
                if (keys.contains(key)) continue;
                Object value = stringObjectEntry.getValue();
                String name = value.getClass().getSimpleName();
                switch (name) {
                    case "Integer":
                        Integer integer = (Integer) existsMap.get(key);
                        Integer gaValue = (Integer) value;
                        Integer re = (integer == null ? 0 : integer) + (gaValue == null ? 0 : gaValue);
                        existsMap.put(key, re);
                        break;
                    case "Double":
                        Double Doubleinteger = (Double) existsMap.get(key);
                        Double DoublegaValue = (Double) value;
                        Double Doublere = (Doubleinteger == null ? 0 : Doubleinteger) + (DoublegaValue == null ? 0 : DoublegaValue);
                        existsMap.put(key, Doublere);
                        break;
                    case "Float":
                        Float Floatinteger = (Float) existsMap.get(key);
                        Float FloatgaValue = (Float) value;
                        Float Floatre = (Floatinteger == null ? 0 : Floatinteger) + (FloatgaValue == null ? 0 : FloatgaValue);
                        existsMap.put(key, Floatre);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    /**
     * 根据键值对查找对应的map，没有找到返回null。 每一个map中都包含所有的keys值
     *
     * @param mapList
     * @param filterKeyMap
     * @return
     */
    private static Map<String, Object> existsMap(List<Map<String, Object>> mapList, Map<String, Object> filterKeyMap) {

        Map<String, Object> resultMap = null;
        for (Map<String, Object> map : mapList) {
            boolean isFound = true;
            for (Map.Entry<String, Object> stringObjectEntry : filterKeyMap.entrySet()) {
                String key = stringObjectEntry.getKey();
                Object value = stringObjectEntry.getValue();
                Object o = map.get(key);
                isFound = isFound && Objects.equal(value, o);
            }

            // 已经找到
            if (isFound) {
                resultMap = map;
                break;
            }
        }
        return resultMap;
    }

    /**
     * 抽取map所有的keys的值
     *
     * @param result
     * @param keys
     * @return
     */
    private static Map<String, Object> extractFilterMap(Map<String, Object> result, Collection<String> keys) {
        Map<String, Object> filterMap = new HashMap<>();
        for (String key : keys) {
            Object o = result.get(key);
            if (o == null) {
                logger.error("result is exist >>>>" + key + "  ;;;;>>>>>>>>" + JSON.toJSONString(result));
            }
            filterMap.put(key, o);
        }
        return filterMap;
    }

    public static void main(String[] args) {
        List<List<Map<String, Object>>> outList = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            List<Map<String, Object>> mapList = new ArrayList<>();
            for (int j = 0; j < 3; j++) {
                Map<String, Object> data = new HashMap<>();
                if (j == 0) {
                    data.put("deviceCategory", "tablet");
                    data.put("age", "14-25");
                    data.put("sessions", j);
                }
                if (j == 1) {
                    data.put("sessions", j);
                    data.put("deviceCategory", "mobile");
                    data.put("age", "26-45");
                }
                if (j == 2) {
                    data.put("sessions", j);
                    if (i == 1) {
                        data.put("age", "55-65");
                    }

                    data.put("deviceCategory", "desktop");
                }
                mapList.add(data);
            }
//            if (i == 0){
//                Map<String, Object> data = new HashMap<>();
//                data.put("sessions", 3);
//                data.put("age", "55-65");
//                data.put("deviceCategory", "desktop1");
//                mapList.add(data);
//            }
            outList.add(mapList);
        }

        System.out.println(JSON.toJSONString(outList));
        List<Map<String, Object>> deviceCategory = mergeMap(outList, Lists.newArrayList("deviceCategory", "age"));
        System.out.println("11111111111111111111111111111111111");
        System.out.println(JSON.toJSONString(deviceCategory));
        System.out.println("2222222222222222222222222222222222");
    }


}
